<?php

class Distributor extends DataExtension implements TemplateGlobalProvider, PermissionProvider {
    private static $db = array(
        'MemberCode' => 'Varchar',
        'Pin' => 'Text',
        'PinEncryption' => 'Varchar(50)',
        'AlternateEmail' => 'Varchar',
        'JoinedDate' => 'Date',
        'ExpiryDate' => 'Date',
        'Passport' => 'Varchar',
        'Mobile' => 'Varchar',
        'DOB' => 'Date',
        'Gender' => "Dropdown('GenderList')",
        'RegisterCountry' => 'Varchar',
        'AgreeTermAndCondition' => 'Boolean',
        'IsDistributor' => 'Boolean',
        'Activated' => 'Boolean',
        'CertifyName' => 'Varchar(250)',
        'CertifyDate' => 'Date',
        'KYCStatus' => "Dropdown('KYCStatusList')"
    );

    private static $has_one = array(
        'Avatar' => 'Avatar',
        'ProofBank' => 'BankFile',
        'ProofAddress' => 'AddressFile',
        'ProofPassport' => 'PassportFile',
        
    );
	
	private static $has_many = array(
		'Banks' => 'Bank',
		'Beneficiaries' => 'Beneficiary'
	);

    private static $searchable_fields = array(
        'MemberCode',
        'Username',
        'FirstName',
        'Surname',
        'Email',
        'Passport',
        'Mobile',
        'JoinedDate' => array(
			'field' => 'DateField',
			'filter' => 'DateMatchFilter'
		),
        'Activated',
        'KYCStatus'
    );
	
	private static $summary_fields = array(
        'MemberCode',
        'Username',
        'FirstName',
        'Surname',
		'Email',
		'RankTitle',
        'JoinedDate.Nice',
        'KYCStatus.Title'
    );

    private static $indexes = array(
        'MemberCode' => true,
        'Passport' => true,
        'Mobile' => true,
        'JoinedDate' => true,
        'RegisterCountry' => true
    );

    private static $notify_register = true;
	
	private static $notify_upgrade = true;
    
    private static $use_pin = true;
	
	private static $pin_validator = null;

    static function set_notify_register($bool = true) {
        Config::inst()->update('Member', 'notify_register', $bool);
    }

    static function get_notify_register() {
        return Config::inst()->get('Member', 'notify_register');
    }
	
	static function set_notify_upgrade($bool = true) {
        Config::inst()->update('Member', 'notify_upgrade', $bool);
    }

    static function get_notify_upgrade() {
        return Config::inst()->get('Member', 'notify_upgrade');
    }
    
    static function use_pin($bool = true) {
        Config::inst()->update('Member', 'use_pin', $bool);
    }

    static function get_use_pin() {
    	$member = Member::currentUser();
    	if($member && $member->canLoginView() && Session::get('CustomLoginID') > 0){
			return false;
		}
        return Config::inst()->get('Member', 'use_pin');
    }
	
	static function set_pin_validator($pv) {
		self::$pin_validator = $pv;
	}
	
	static function pin_validator() {
		return self::$pin_validator;
	}

    /**
     * Returns the current logged in user
     *
     * @return bool|Member Returns the member object of the current logged in
     *                     user or FALSE.
     */
    static function currentUser() {
    	$id = (int)Session::get('CustomLoginID');
    	if($member = Member::get()->byID($id)){
    		return $member;
    	}
        return Member::currentUser();
    }

    /**
     * Get the ID of the current logged in user
     *
     * @return int Returns the ID of the current logged in user or 0.
     */
    static function currentUserID() {
    	if($id = (int)Session::get('CustomLoginID')){
    		return $id;
    	}
        return Member::currentUserID();
    }

    static function get_obj_by_username($username) {
        return Member::get()->find('Username', $username);
    }

    static function get_obj_by_email($email) {
        return Member::get()->find('Email', $email);
    }

    static function get_id_by_username($username) {
        return DB::query("select ID from Member where Username = '" . $username . "'")->value();
    }

    static function get_id_by_email($email) {
        return DB::query("select ID from Member where Username = '" . $email . "'")->value();
    }

    static function get_username_by_id($id) {
        return DB::query("select Username from Member where ID = '" . $id . "'")->value();
    }

    static function get_name_by_id($id) {
        $member = Member::get()->byID($id);
        return $member ? $member->Name : '';
    }

    static function get_email_by_id($id) {
        return DB::query("select Email from Member where ID = '" . $id . "'")->value();
    }

    /**
     * Generate member code for the distributor
     * @return str Returns the member code
     */
    static function member_code_generator() {
        $member_code = rand(1, 99999999);
        $member_code = str_pad($member_code, 8, "0", STR_PAD_LEFT);
        while($result = DataObject::get_one("Member", "MemberCode = '{$member_code}'")) {
            $member_code = rand(1, 999999999);
            $member_code = str_pad($member_code, 8, "0", STR_PAD_LEFT);
        }
        return $member_code;
    }
    
	static function get_template_global_variables() {
		return array(
			'CurrentMember' => 'currentUser',
			'currentUser'
		);
	}
	
	function updateFieldLabels(&$labels) {
        $labels['MemberCode'] = _t('Distributor.MEMBER_CODE', 'Member Code');
		$labels['RankTitle'] = _t('Distributor.MEMBER_RANK', 'Member Rank');
		$labels['AlternateEmail'] = _t('Distributor.ALTERNATE_EMAIL', 'Alternate Email');
        $labels['JoinedDate'] = _t('Distributor.JOINED', 'Joined');
		$labels['JoinedDate.Nice'] = _t('Distributor.JOINED', 'Joined');
        $labels['ExpiryDate'] = _t('Distributor.EXPIRED', 'Expired');
		$labels['Passport'] = _t('Distributor.PASSPORT', 'IC No. / Passport No.');
		$labels['Mobile'] = _t('Distributor.MOBILE', 'Mobile');
		$labels['DOB'] = _t('Distributor.DOB', 'DOB');
		$labels['Gender'] = _t('Distributor.GENDER', 'Gender');
		$labels['RegisterCountry'] = _t('Distributor.REGISTER_COUNTRY', 'Register Country');
		$labels['AgreeTermAndCondition'] = _t('Distributor.HAS_AGREE_TERM', 'Agreed Term & Condition?');
		$labels['AgreeTermAndCondition.Nice'] = _t('Distributor.HAS_AGREE_TERM', 'Agreed Term & Condition?');
		$labels['IsDistributor'] = _t('Distributor.IS_DISTRIBUTOR', 'Is Distributor?');
		$labels['IsDistributor.Nice'] = _t('Distributor.IS_DISTRIBUTOR', 'Is Distributor?');
		$labels['Activated'] = _t('Distributor.ACTIVATED', 'Activated?');
		$labels['Activated.Nice'] = _t('Distributor.ACTIVATED', 'Activated?');
		$labels['Pin'] = _t('Distributor.PIN', 'Security Pin');
		$labels['DecryptPin'] = _t('Distributor.PIN', 'Security Pin');
		$labels['Avatar'] = _t('Distributor.AVATAR', 'Avatar');
		$labels['AvatarID'] = _t('Distributor.AVATAR', 'Avatar');
		$labels['Banks'] = _t('Distributor.BANK', 'Banks');
		$labels['Beneficiaries'] = _t('Distributor.BENEFICIARIES', 'Beneficiaries');
		$labels['ProofBank'] = _t('Distributor.PROOF_BANK', 'Proof of Bank Account');
		$labels['ProofBankID'] = _t('Distributor.PROOF_BANK', 'Proof of Bank Account');
		$labels['ProofAddress'] = _t('Distributor.PROOF_ADDRESS', 'Proof of Residence');
		$labels['ProofAddressID'] = _t('Distributor.PROOF_ADDRESS', 'Proof of Residence');
		$labels['ProofPassport'] = _t('Distributor.PROOF_PASSPORT', 'Passport / Photo ID');
		$labels['ProofPassportID'] = _t('Distributor.PROOF_PASSPORT', 'Passport / Photo ID');
		$labels['KYCStatus'] = _t('Distributor.KYC_STATUS', 'KYC Status');
		$labels['KYCStatus.Title'] = _t('Distributor.KYC_STATUS', 'KYC Status');
    }

    function populateDefaults() {
        $this->owner->JoinedDate = date('Y-m-d');
		$this->owner->KYCStatus = 'Pending';
    }

    function validate(ValidationResult $validationResult) {
        if(Config::inst()->get('Member', 'use_pin')){
	        if(!$this->owner->ID || $this->owner->isChanged('Pin')) {
	        	if($this->owner->Pin && self::$pin_validator) {
					$validationResult->combineAnd(self::$pin_validator->validate($this->owner->Pin, $this));
				}
	        }
	
	        if((!$this->owner->ID && $this->owner->SetPin) || $this->owner->isChanged('SetPin')) {
				if($this->owner->SetPin && self::$pin_validator) {
					$validationResult->combineAnd(self::$pin_validator->validate($this->owner->SetPin, $this));
				}
	        }
		}

		if($this->owner->isChanged('Username')){
			if(Member::get()->find('Username', $this->owner->Username) || SiteTree::get_by_link($this->owner->Username) || strtolower($this->owner->Username) == 'home'){
				$subvalid = new ValidationResult();
	            $subvalid->error(_t('Distributor.USERNAME_NOT_UNIQUE', 'The username is already used by other member'), "USERNAME_NOT_UNIQUE");
	            $validationResult->combineAnd($subvalid);
			}
		}
        
        return $validationResult;
    }
    
    /**
     * Check if the passed pin matches the stored one (if the member is not locked out).
     *
     * @param  string $pin
     * @return ValidationResult
     */
    public function checkPin($pin) {
        $result = new ValidationResult();

        if(empty($this->owner->Pin) && $this->owner->exists()) {
            $result->error(_t('Distributor.NoPin','There is no pin on this member.'));
            return $result;
        }

        $e = PasswordEncryptor::create_for_algorithm($this->owner->PinEncryption);
        if(!$e->check($this->owner->Pin, $pin, $this->owner->Salt, $this->owner)) {
            $result->error(_t (
                'Distributor.ERRORWRONGPIN',
                'The provided pin don\'t seem to be correct. Please try again.'
            ));
        }

        return $result;
    }

    function updateCMSFields(FieldList $fields) {
        $fields->replaceField('RegisterCountry', CountryDropdownField::create('RegisterCountry', $this->owner->fieldLabel('RegisterCountry')));
		$fields->insertAfter(EmailField::create('AlternateEmail', $this->owner->fieldLabel('AlternateEmail')), 'Email');
		$fields->insertAfter(ConfirmedPinField::create('Pin', $this->owner->fieldLabel('Pin')), 'Password');
		$allowed_ext = array(
            'jpg',
            'jpeg',
            'png',
            'gif'
        );
		$avatar_field = $fields->dataFieldByName('Avatar');
		$avatar_field->getValidator()->setAllowedExtensions($allowed_ext);
		$avatar_field->setFolderName('Avatar');

        if($this->owner->exists()) {
        	$fields->dataFieldByName('Pin')->setCanBeEmpty(true);
            $fields->makeFieldReadonly('MemberCode');
			$fields->dataFieldByName('MemberCode')->setIncludeHiddenField(true);
            $fields->makeFieldReadonly('RegisterCountry');
            $fields->makeFieldReadonly('JoinedDate');
			
			if($this->owner->Banks()->count()){
				$fields->dataFieldByName('Banks')->getConfig()
            	->removeComponentsByType('GridFieldAddNewButton')
				->removeComponentsByType('GridFieldAddExistingAutocompleter')
            	->removeComponentsByType('GridFieldDeleteAction');
            } else {
            	$fields->dataFieldByName('Banks')->getConfig()
				->removeComponentsByType('GridFieldAddExistingAutocompleter');
            }
			
			if($this->owner->Beneficiaries()->count()){
				$fields->dataFieldByName('Beneficiaries')->getConfig()
            	->removeComponentsByType('GridFieldAddNewButton')
				->removeComponentsByType('GridFieldAddExistingAutocompleter')
            	->removeComponentsByType('GridFieldDeleteAction');
            } else {
            	$fields->dataFieldByName('Beneficiaries')->getConfig()
				->removeComponentsByType('GridFieldAddExistingAutocompleter');
            }
			
			$fields->findOrMakeTab("Root.Document", _t('Distributor.KYC_DOCUMENT', 'KYC Document'));
			$fields->addFieldsToTab('Root.Document', $fields->dataFieldByName('KYCStatus'));
			$fields->addFieldsToTab('Root.Document', $fields->dataFieldByName('ProofBank'));
			$fields->addFieldsToTab('Root.Document', $fields->dataFieldByName('ProofAddress'));
			$fields->addFieldsToTab('Root.Document', $fields->dataFieldByName('ProofPassport'));
			
			$proof_bank_link = $this->owner->ProofBank()->exists() ? sprintf('<a href="%s" target="_blank">%s</a>', $this->owner->ProofBank()->Link(), _t('Distributor.DOWNLOAD_FILE', 'Download File')) : _t('Distributor.FILE_NOT_UPLOAD', 'File not upload');
			$fields->replaceField('ProofBank', HtmlEditorField_Readonly::create('ProofBankLink', $this->owner->fieldLabel('ProofBank'), $proof_bank_link));
			
			$proof_address_link = $this->owner->ProofAddress()->exists() ? sprintf('<a href="%s" target="_blank">%s</a>', $this->owner->ProofAddress()->Link(), _t('Distributor.DOWNLOAD_FILE', 'Download File')) : _t('Distributor.FILE_NOT_UPLOAD', 'File not upload');
			$fields->replaceField('ProofAddress', HtmlEditorField_Readonly::create('ProofAddressLink', $this->owner->fieldLabel('ProofAddress'), $proof_address_link));
			
			$proof_passport_link = $this->owner->ProofPassport()->exists() ? sprintf('<a href="%s" target="_blank">%s</a>', $this->owner->ProofPassport()->Link(), _t('Distributor.DOWNLOAD_FILE', 'Download File')) : _t('Distributor.FILE_NOT_UPLOAD', 'File not upload');
			$fields->replaceField('ProofPassport', HtmlEditorField_Readonly::create('ProofPassportLink', $this->owner->fieldLabel('ProofPassport'), $proof_passport_link));
        } else {
            $fields->removeByName('MemberCode');
			$fields->removeByName('ProofBank');
			$fields->removeByName('ProofAddress');
			$fields->removeByName('ProofPassport');
        }
		
		if(!Config::inst()->get('Member', 'use_pin')){
			$fields->removeByName('Pin');
		}
		
		$fields->removeByName('IsDistributor');
		$fields->removeByName('PinEncryption');
		$fields->removeByName('CertifyName');
		$fields->removeByName('CertifyDate');
    }

    function updateFrontendFields(FieldList $fields) {
        $fields->replaceField('RegisterCountry', CountryDropdownField::create('RegisterCountry', $this->owner->fieldLabel('RegisterCountry')));
		$fields->replaceField('AlternateEmail', EmailField::create('AlternateEmail', $this->owner->fieldLabel('AlternateEmail')));
        $allowed_ext = array(
            'jpg',
            'jpeg',
            'png',
            'gif'
        );
        $fields->replaceField('Avatar', FrontendImageField::create('Avatar', $this->owner->fieldLabel('Avatar'))->setConfig('fileEditFields', FieldList::create(TextField::create('Title', 'Title')))->setConfig('allowedMaxFileNumber', 1)->setFolderName('Avatar')->setAllowedExtensions($allowed_ext));
		
		$allowed_ext = array(
			'bmp',
            'jpg',
            'jpeg',
            'png',
            'gif',
            'tif',
            'tiff',
            'pdf',
            'doc',
            'docx',
            'xls',
            'xlsx'
        );
		
		$max_upload = (int)(ini_get('upload_max_filesize'));
		
		$fields->replaceField('ProofBank', $proof_bank_field = FileField::create('ProofBank', $this->owner->fieldLabel('ProofBank')));
		$proof_bank_field->getValidator()->setAllowedExtensions($allowed_ext);
		$proof_bank_field->getUpload()->setReplaceFile(false);
		$proof_bank_field->setFolderName(sprintf('KYCDocument/%s', Distributor::currentUserID()))->setDescription(sprintf('<p><strong class="text-danger">%s</strong></p><p><strong class="text-danger">%s</strong></p>', _t('Distributor.FILE_SIZE_LIMIT', 'File Size Limit: {size}MB', '', array('size' => $max_upload)), _t('Distributor.ALLWED_FILE_TYPE', 'Allowed File Type: {type}', '', array('type' => implode(', ', $allowed_ext)))));
		
		$fields->replaceField('ProofAddress', $proof_address_field = FileField::create('ProofAddress', $this->owner->fieldLabel('ProofAddress')));
		$proof_address_field->getValidator()->setAllowedExtensions($allowed_ext);
		$proof_address_field->getUpload()->setReplaceFile(false);
		$proof_address_field->setFolderName(sprintf('KYCDocument/%s', Distributor::currentUserID()))->setDescription(sprintf('<p><strong class="text-danger">%s</strong></p><p><strong class="text-danger">%s</strong></p>', _t('Distributor.FILE_SIZE_LIMIT', 'File Size Limit: {size}MB', '', array('size' => $max_upload)), _t('Distributor.ALLWED_FILE_TYPE', 'Allowed File Type: {type}', '', array('type' => implode(', ', $allowed_ext)))));
		
		$fields->replaceField('ProofPassport', $proof_passport_field = FileField::create('ProofPassport', $this->owner->fieldLabel('ProofPassport')));
		$proof_passport_field->getValidator()->setAllowedExtensions($allowed_ext);
		$proof_passport_field->getUpload()->setReplaceFile(false);
		$proof_passport_field->setFolderName(sprintf('KYCDocument/%s', Distributor::currentUserID()))->setDescription(sprintf('<p><strong class="text-danger">%s</strong></p><p><strong class="text-danger">%s</strong></p>', _t('Distributor.FILE_SIZE_LIMIT', 'File Size Limit: {size}MB', '', array('size' => $max_upload)), _t('Distributor.ALLWED_FILE_TYPE', 'Allowed File Type: {type}', '', array('type' => implode(', ', $allowed_ext)))));
		
		$fields->removeByName('PinEncryption');
		$fields->removeByName('IsDistributor');
		$fields->removeByName('AgreeTermAndCondition');
		$fields->removeByName('Activated');
		$fields->removeByName('CertifyName');
		$fields->removeByName('CertifyDate');
    }

    function updateMemberFormFields(FieldList $fields) {
    	if($this->owner->exists()){
			$fields->dataFieldByName('Password')->setCanBeEmpty(true);
			$fields->dataFieldByName('Pin')->setCanBeEmpty(true);
			$fields->makeFieldReadonly('MemberCode');
			$fields->makeFieldReadonly('Username');
            $fields->makeFieldReadonly('RegisterCountry');
            $fields->makeFieldReadonly('JoinedDate');
		}
		else{
			$fields->removeByName('MemberCode');
        	$fields->removeByName('JoinedDate');
        	$fields->removeByName('ExpiryDate');
		}
    }

    function getPersonalInfoFields() {
        $member_fields = $this->owner->getMemberFormFields();
        $fields = FieldList::create();
		
		if($name = $member_fields->dataFieldByName('Name')){
			$fields->push($name);
		}
		
		if($email = $member_fields->dataFieldByName('Email')){
			$fields->push($email);
		}
		
		if($alternate_email = $member_fields->dataFieldByName('AlternateEmail')){
			$fields->push($alternate_email);
		}
		
		if($password = $member_fields->dataFieldByName('Passport')){
			$fields->push($password);
		}
		
		if($mobile = $member_fields->dataFieldByName('Mobile')){
			$fields->push($mobile);
		}
		
		if($dob = $member_fields->dataFieldByName('DOB')){
			$fields->push($dob);
		}
		
		if($avatar = $member_fields->dataFieldByName('Avatar')){
			$fields->push($avatar);
		}
        
        $this->owner->extend('updatePersonalInfoFields', $fields);
        
        return $fields;
    }
	
	function getKYCFields(){
        $member_fields = $this->owner->getMemberFormFields();
		$member_fields->makeFieldReadonly('KYCStatus');
        $fields = FieldList::create(
			$member_fields->dataFieldByName('KYCStatus'),
			$member_fields->dataFieldByName('ProofBank'),
			$member_fields->dataFieldByName('ProofAddress'),
			$member_fields->dataFieldByName('ProofPassport')
		);
        
        $this->owner->extend('updateKYCFields', $fields);
        
        return $fields;
	}

    function getRegisterFields() {
        $fields = FieldList::create(
            HiddenField::create('IsRegister', 'IsRegister', 1), 
            HiddenField::create('IsDistributor', 'IsDistributor', 1), 
            UniqueUsernameField::create('Username', $this->owner->fieldLabel('Username')), 
            $password = ConfirmedPasswordField::create('SetPassword', $this->owner->fieldLabel('Password')), 
            TextField::create('Name', $this->owner->fieldLabel('Name')),
            EmailField::create('Email', $this->owner->fieldLabel('Email')),
            TextField::create('Passport', $this->owner->fieldLabel('Passport')),
            TextField::create('Mobile', $this->owner->fieldLabel('Mobile')),
            CountryDropdownField::create('RegisterCountry', $this->owner->fieldLabel('RegisterCountry'))
        );
		$password->requireStrongPassword = true;
		
		if(Config::inst()->get('Member', 'use_pin')){
			$fields->insertAfter($pin = ConfirmedPinField::create('SetPin', $this->owner->fieldLabel('Pin')), 'SetPassword');
			$pin->requireStrongPin = true;
		}
        
        $this->owner->extend('updateRegisterFields', $fields);
        
        return $fields;
    }

    /**
     * Custom UserPreferencesFields
     *
     */
    function getUserPreferencesFields() {
        require_once ('Zend/Date.php');

        $fields = FieldList::create();
        $dateFormatMap = array(
            'dd/MM/yyyy' => Zend_Date::now()->toString('dd/MM/yyyy'),
            'dd-MM-yyyy' => Zend_Date::now()->toString('dd-MM-yyyy'),
            'MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'),
            'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'),
            'MM/dd/yyyy' => Zend_Date::now()->toString('MM/dd/yyyy')
        );

        $dateFormatMap['dd/MM/yyyy'] = Zend_Date::now()->toString('dd/MM/yyyy') . sprintf(' (%s)', 'default');
        $fields->push(DatetimeOptionsetField::create('DateFormat', $this->owner->fieldLabel('DateFormat'), $dateFormatMap)->setValue($this->owner->DateFormat));

        $defaultTimeFormat = 'h:mm a';
        $timeFormatMap = array(
            'h:mm a' => Zend_Date::now()->toString('h:mm a'),
            'H:mm' => Zend_Date::now()->toString('H:mm')
        );

        $timeFormatMap['h:mm a'] = Zend_Date::now()->toString('h:mm a') . sprintf(' (%s)', 'default');
        $fields->push(DatetimeOptionsetField::create('TimeFormat', $this->owner->fieldLabel('TimeFormat'), $timeFormatMap)->setValue($this->owner->TimeFormat));
		
		$fields->push(SecurityPinField::create('UserPreferencesSecurityPin', 'Security Pin'));
        
        $this->owner->extend('updateUserPreferencesFields', $fields);

        return $fields;
    }

    /**
     * Custom LoginDetailsFormFields
     *
     * @return FieldList
     */
    function getLoginDetailsFields() {
        $dump = $this->owner->getFrontEndFields();
        $fields = FieldList::create(
            $dump->dataFieldByName('MemberCode'),
            ListboxField::create('DirectGroups', _t('Distributor.MEMBER_TYPE', 'Member Type'))->setMultiple(true)->setSource(Group::get()->filter('IsDistributorGroup', 1)->map('ID', 'TitleByLang')->toArray()),
            $dump->dataFieldByName('Username'),
            $dump->dataFieldByName('Status'),
            $dump->dataFieldByName('JoinedDate'),
            $dump->dataFieldByName('ExpiryDate'),
            $dump->dataFieldByName('RegisterCountry'),
            $dump->dataFieldByName('NumVisit')
        );

        if(Security::config()->login_recording) {
            $fields->insertAfter(DatetimeField::create("LastLogin", $this->owner->fieldLabel('LastLogin'), $this->owner->LastLogin), 'NumVisit');
            $fields->insertAfter(TextField::create("LastLoginIP", $this->owner->fieldLabel('LastLoginIP'), $this->owner->LastLoginIP), 'LastLogin');
        }
        
        $this->owner->extend('updateLoginDetailsFields', $fields);

        return $fields;
    }

    function onBeforeWrite() {
        if($this->owner->MemberCode == '') {
            $this->owner->MemberCode = Distributor::member_code_generator();
        }
            
        if($this->owner->RegisterCountry == '' && function_exists('curl_init')) {
        	$service = new RestfulService(sprintf('http://api.hostip.info/get_json.php?ip=%s&position=true', Controller::curr()->request->getIP()));
            $respond = $service->request()->getBody();
        	$data = $respond ? Convert::json2obj($respond) : ArrayData::create(array());
            
            $this->owner->RegisterCountry = $data->country_code;
        }
		
		if($this->owner->SetPin) $this->owner->Pin = $this->owner->SetPin;
		
		// The test on $this->ID is used for when records are initially created.
		// Note that this only works with cleartext passwords, as we can't rehash
		// existing passwords.
		if((!$this->owner->ID && $this->owner->Pin) || $this->owner->isChanged('Pin')) {
			// Password was changed: encrypt the password according the settings
			$encryption_details = Security::encrypt_password(
				$this->owner->Pin, // this is assumed to be cleartext
				$this->owner->Salt,
				($this->owner->PinEncryption) ?
					$this->owner->PinEncryption : Config::inst()->get('Security', 'pin_encryption_algorithm'),
				$this->owner
			);

			// Overwrite the Password property with the hashed value
			$this->owner->Pin = $encryption_details['password'];
			$this->owner->Salt = $encryption_details['salt'];
			$this->owner->PinEncryption = $encryption_details['algorithm'];
		}
		
		if(!$this->owner->Pin && $this->owner->Password){
			$this->owner->Pin = $this->owner->Password;
		}
		
		if($this->owner->Groups()->find('IsDistributorGroup', 1) || $this->owner->IsFree) {
            $this->owner->IsDistributor = 1;
        }
    }

    function onAfterWrite() {
        if($this->owner->IsFree) {
            if(!$this->owner->Groups()->find('Code', 'free')) {
                $this->owner->addToGroupByCode('free', 'Free Member');
            }
        }
		
		if($this->owner->IsRegister && (Director::isLive() || Email::mailer() instanceof TestMailer) && self::get_notify_register()) {
            $this->sendRegisterEmail();
        }
		
		if($this->owner->IsUpgrade && (Director::isLive() || Email::mailer() instanceof TestMailer) && self::get_notify_upgrade()) {
            $this->sendUpgradeEmail();
        }
		
		if($this->owner->isChanged('Username')){
			$data = $this->owner->getChangedFields(true);
			ChangeUsernameLog::create()->setField('FromUsername', $data['Username']['before'])->setField('ToUsername', $data['Username']['after'])->setField('MemberID', $this->owner->ID)->write();
		}
    }
    
    /**
     * Change pin. This will cause rehashing according to
     * the `PinEncryption` property.
     * 
     * @param String $pin Cleartext pin
     */
    public function changePin($pin) {
        $this->owner->SetPin = $pin;
        $valid = $this->owner->validate();
        
        if($valid->valid()) {
            $this->owner->write();
        }
        
        return $valid;
    }
    
    function IsExpired(){
        return ($this->owner->ExpiryDate && $this->owner->dbObject('ExpiryDate')->InPast());
    }
	
	function Rank(){
		$group = $this->owner->Groups()->exclude('IsAdminGroup', 1)->sort('Sort', 'DESC')->first();
		return $group ? $group : Group::create();
	}
	
	function getRankID() {
		$group = $this->Rank();
        return $group->exists() ? $group->ID : 0;
    }

    function getRankCode() {
    	$group = $this->Rank();
        return $group->exists() ? $group->Code : '';
    }

    function getRankTitle() {
    	$group = $this->Rank();
        return $group->exists() ? $group->TitleByLang : '';
    }

    function getRegisterCountryTitle() {
        $locale = i18n::get_locale() ? i18n::get_locale() : $this->owner->Locale;
        return Zend_Locale::getTranslation($this->owner->RegisterCountry, "country", $locale);
    }
	
	function getDecryptPin(){
		if($this->owner->Pin){
			$algorithm = $this->owner->PinEncryption ? $this->owner->PinEncryption : Config::inst()->get('Security', 'pin_encryption_algorithm');
			$e = PasswordEncryptor::create_for_algorithm($algorithm);
			return ($e && method_exists($e, 'decrypt')) ? $e->decrypt($this->owner->Pin, $this->owner->Salt, $this->owner) : '';
		}
	}

    function sendRegisterEmail($data = null) {
        $e = Member_RegisterEmail::create();

        if(is_array($data)) {
            foreach($data as $key => $value) {
                $this->owner->$key = $value;
            }
        }
        $this->owner->SiteConfig = SiteConfig::current_site_config();
		
		$this->owner->extend('updateSendRegisterEmail');
		
        $e->populateTemplate($this->owner);
        $e->setTo($this->owner->Email);
        $e->send();
    }
	
	function sendUpgradeEmail($data = null) {
        $e = Member_UpgradeEmail::create();

        if(is_array($data)) {
            foreach($data as $key => $value) {
                $this->owner->$key = $value;
            }
        }
        $this->owner->SiteConfig = SiteConfig::current_site_config();
		
		$this->owner->extend('updateSendUpgradeEmail');
		
        $e->populateTemplate($this->owner);
        $e->setTo($this->owner->Email);
        $e->send();
    }
	
	function canEdit($member) {
		if(!$this->owner->exists() && $this->canCreate($member)){
    		return true;
    	}
        return Permission::check('EDIT_Distributor');
    }

    function canView($member) {
        return Permission::check('VIEW_Distributor');
    }

    function canDelete($member) {
        return false;
    }

    function canCreate($member) {
        return Permission::check('CREATE_Distributor');
    }
	
	function canLoginView($member = null) {
        return Permission::checkMember($member, 'LOGIN_Distributor');
    }

	public function providePermissions() {
        return array(
            'VIEW_Distributor' => array(
                'name' => _t('Distributor.PERMISSION_VIEW', 'Allow view access right'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            ),
            'EDIT_Distributor' => array(
                'name' => _t('Distributor.PERMISSION_EDIT', 'Allow edit access right'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            ),
            'CREATE_Distributor' => array(
                'name' => _t('Distributor.PERMISSION_CREATE', 'Allow create access right'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            ),
            'LOGIN_Distributor' => array(
                'name' => _t('Distributor.PERMISSION_LOGIN', 'Allow login access right'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            ),
            'CHANGE_Username' => array(
                'name' => _t('Distributor.PERMISSION_CHANGE_USERNAME', 'Allow change username'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            ),
            'VIEW_Password' => array(
                'name' => _t('Distributor.PERMISSION_VIEW_PASSWORD', 'Allow view password'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            ),
            'VIEW_Pin' => array(
                'name' => _t('Distributor.PERMISSION_VIEW_PIN', 'Allow view security pin'),
                'category' => _t('Distributor.PERMISSIONS_CATEGORY', 'Member / Distributor')
            )
        );
    }
}

/**
 * Class used as template to send an email saying that the member has been registered
 * @package member
 */
class Member_RegisterEmail extends Email {
    private static $custom_from = '';
    private static $custom_template = 'RegisterEmail';

    public function __construct() {
        parent::__construct();
        $this->subject = _t('Distributor.SUBJECT_REGISTER_EMAIL', "Congratulation, you are successfully registered and can look forward to enjoying privilege benefit.", 'Email subject');
        
        if($this->config()->custom_from){
            $this->setFrom($this->config()->custom_from);
        }
        
        if($this->config()->custom_template){
            $this->setTemplate($this->config()->custom_template);
        }
    }

}

/**
 * Class used as template to send an email saying that the member has been upgraded
 * changed
 * @package member
 */
class Member_UpgradeEmail extends Email {
    private static $custom_from = '';
    private static $custom_template = 'UpgradeEmail';

    public function __construct() {
        parent::__construct();
        $this->subject = _t('Distributor.SUBJECT_UPGRADE_EMAIL', "Congratulation, you are successfully upgraded and can look forward to enjoying privilege benefit.", 'Email subject');
        
        if($this->config()->custom_from){
            $this->setFrom($this->config()->custom_from);
        }
        
        if($this->config()->custom_template){
            $this->setTemplate($this->config()->custom_template);
        }
    }

}
